﻿using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.U2D;

//------------------------------------------------------------
// shaco Framework
// Copyright © 2017-2021 chang.liu All rights reserved.
// Feedback: 449612236@qq.com
//------------------------------------------------------------

namespace shaco
{
    /// <summary>
    /// 图集配置类
    /// </summary>
    public class SpriteAtlasSettings : ScriptableObject, ISpriteAtlasSettings, shaco.Base.IGameInstanceCreator
    {
        public const string SETTINGS_PATH_KEY = "shaco.RuntimeSpriteAtlasSettings";

        [SerializeField]
        private List<SpriteAtlasSettingsInfo> _atlasInfo = new List<SpriteAtlasSettingsInfo>();

        private Dictionary<string, SpriteAtlasSettingsInfo> _atlasNameDic = new Dictionary<string, SpriteAtlasSettingsInfo>();
        private Dictionary<string, SpriteAtlasSettingsInfo> _atlasPathDic = new Dictionary<string, SpriteAtlasSettingsInfo>();

        private Dictionary<string, string> _atlasNameToFolder = null;
        private System.Text.StringBuilder _appendStringCache = new System.Text.StringBuilder();

        static public object Create()
        {
            return ScriptableObject.CreateInstance<SpriteAtlasSettings>();
        }

        public void ClearUnused()
        {
            for (int i = _atlasInfo.Count - 1; i >= 0; --i)
            {
                var iter = _atlasInfo[i];
                var loadPath = $"{iter.atlasFolder}/{iter.atlasName}.spriteatlas";
                var existsAsset = true;
#if UNITY_EDITOR
                existsAsset = null != AssetDatabase.LoadAssetAtPath<SpriteAtlas>(loadPath);
#else
                existsAsset = shaco.GameHelper.res.Exists(loadPath);
#endif
                if (existsAsset)
                    continue;

                //删除无效文件
                _atlasNameDic.Remove(iter.atlasName);
                _atlasPathDic.Remove(iter.atlasFolder);
                _atlasInfo.RemoveAt(i);
            }
        }

        void Clear()
        {
            _atlasInfo.Clear();
            _atlasNameDic.Clear();
            _atlasPathDic.Clear();
        }

        public void AddAtlasInfo(SpriteAtlasSettingsInfo info)
        {
            if (_atlasNameDic.ContainsKey(info.atlasName))
            {
                Log.Error("SpriteAtlasSettings AddAtlasInfo error: duplicate atlas name=" + info.atlasName + "\npath=" + info.atlasFolder);
                return;
            }

            if (_atlasPathDic.ContainsKey(info.atlasFolder))
            {
                Log.Error("SpriteAtlasSettings AddAtlasInfo error: duplicate atlas path=" + info.atlasFolder + "\nname=" + info.atlasName);
                return;
            }

            if (_atlasInfo.Any(v => v.atlasName == info.atlasName))
                return;

            _atlasInfo.Add(info);
            _atlasNameDic.Add(info.atlasName, info);
            _atlasPathDic.Add(info.atlasFolder, info);
        }

        public bool ContainsAtlasName(string atlasName)
        {
            return _atlasNameDic.ContainsKey(atlasName);
        }

        public bool ContainsAtlasPath(string atlasFolderPath)
        {
            return _atlasPathDic.ContainsKey(atlasFolderPath);
        }

        public string GetAtlasPath(string atlasName)
        {
            var folderPath = GetAtlasFolderPath(atlasName);
            string retValue = string.Empty;

            lock (_appendStringCache)
            {
                _appendStringCache.Length = 0;

                if (string.IsNullOrEmpty(folderPath))
                {
                    _appendStringCache.Append(atlasName);
                }
                else
                {
                    _appendStringCache.Append(folderPath);
                    _appendStringCache.Append(shaco.Base.FileDefine.PATH_FLAG_SPLIT);
                    _appendStringCache.Append(atlasName);
                }
                retValue = _appendStringCache.ToString();
            }
            return retValue;
        }

        public string GetAtlasFolderPath(string atlasName)
        {
            CheckInit();

            string findFolder = null;
            if (!_atlasNameToFolder.TryGetValue(atlasName, out findFolder))
            {
                //如果没有获取到图集文件夹名字，则视为没有开启自动化图集配置
                // Log.Error("SpriteAtlasSettings GetAtlasFolderPath error: not found altasName=" + atlasName);
                return string.Empty;
            }
            return findFolder;
        }

        private void CheckInit()
        {
            if (null != _atlasNameToFolder)
                return;

            _atlasNameToFolder = new Dictionary<string, string>();

            var settingPath = shaco.GameHelper.gameConfig.ReadString(shaco.SpriteAtlasSettings.SETTINGS_PATH_KEY);
            if (string.IsNullOrEmpty(settingPath))
            {
                //如果想开启自动化图集优化功能，需要使用SpriteAtlasSettingsWindow窗口创建一个运行时图集配置文件
                Log.Warning("SpriteAtlasSettings CheckInit warning: unsupport auto atlas referece, please use 'SpriteAtlasSettingsWindow' to create it");
                return;
            }

            this.Clear();

            var loadSettings = GameHelper.res.Load<SpriteAtlasSettings>(settingPath).assetObject as SpriteAtlasSettings;
            for (int i = loadSettings._atlasInfo.Count - 1; i >= 0; --i)
                AddAtlasInfo(loadSettings._atlasInfo[i]);

            if (_atlasInfo.IsNullOrEmpty())
            {
                Log.Error("SpriteAtlasSettings CheckInit erorr: altas info is empty, make sure it correct, path=" + settingPath);
                return;
            }

            for (int i = 0; i < _atlasInfo.Count; ++i)
            {
                var info = _atlasInfo[i];
                if (_atlasNameToFolder.ContainsKey(info.atlasName))
                {
                    Log.Error("SpriteAtlasSettings CheckInit error: duplicate key=" + info.atlasName + " path=" + settingPath);
                    continue;
                }
                _atlasNameToFolder.Add(info.atlasName, info.atlasFolder);
            }
        }
    }
}